added Feb 2001 SDK
[windows-sources.git] / shared source / sscli20 / tools / binplace / binplace.c
blobff2cce931ad1720f870f29a5f261227a4acb1cdc
1 // ==++==
2 //
3 //
4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
5 //
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
10 //
11 // You must not remove this notice, or any other, from this software.
12 //
14 // ==--==
15 #include <rotor_pal.h>
16 #include <palstartup.h>
18 #define BINPLACE_ERR 77
19 #define BINPLACE_OK 0
21 BOOL fUsage;
22 BOOL fVerbose;
23 BOOL fTestMode;
24 BOOL fSetupModeAllFiles;
25 BOOL fSetupModeScriptFile;
26 BOOL fKeepAttributes;
27 BOOL fDontLog;
28 BOOL fMakeErrorOnDumpCopy;
29 BOOL fDontExit;
30 BOOL fSignCode;
31 BOOL fChangeAsmsToRetailForSymbols;
32 BOOL fSrcControl;
33 BOOL fDbgControl;
36 LPSTR CurrentImageName;
37 LPSTR PlaceFileName;
38 LPSTR PlaceRootName;
39 LPSTR DumpOverride;
40 LPSTR NormalPlaceSubdir;
41 LPSTR CommandScriptName;
42 LPSTR SymbolFilePath;
43 LPSTR PrivateSymbolFilePath;
44 LPSTR BinplaceLcDir;
45 LPSTR LcFilePart;
47 FILE *PlaceFile;
48 FILE *CommandScriptFile;
49 CHAR* gDelayLoadModule;
50 CHAR* gDelayLoadHandler;
51 CHAR gFullFileName[MAX_PATH+1];
52 UCHAR SetupFilePath[ MAX_PATH+1 ];
53 UCHAR DebugFilePath[ MAX_PATH+1 ];
54 UCHAR PlaceFilePath[ MAX_PATH+1 ];
55 UCHAR DefaultSymbolFilePath[ MAX_PATH+1 ];
56 UCHAR szAltPlaceRoot[ MAX_PATH+1 ];
59 struct {
60 int RC;
61 CHAR **Argv;
62 int Argc;
63 } ImageCheck;
65 #define DEFAULT_PLACE_FILE "\\public\\sdk\\lib\\placefil.txt"
66 #define DEFAULT_NTROOT "\\nt"
67 #define DEFAULT_NTDRIVE "c:"
68 #define DEFAULT_DUMP "dump"
69 #define DEFAULT_LCDIR "LcINF"
71 typedef struct _CLASS_TABLE {
72 LPSTR ClassName;
73 LPSTR ClassLocation;
74 } CLASS_TABLE, *PCLASS_TABLE;
76 BOOL
77 PlaceTheFile();
80 BOOL
81 CopyTheFile(
82 LPSTR SourceFileName,
83 LPSTR SourceFilePart,
84 LPSTR DestinationSubdir,
85 LPSTR DestinationFilePart
88 BOOL
89 BinplaceCopyPdb (
90 LPSTR DestinationFile,
91 LPSTR SourceFileName, // Used for redist case
92 BOOL CopyFromSourceOnly,
93 BOOL StripPrivate
95 BOOL
96 BinplaceCopyIldb (
97 LPSTR DestinationFile,
98 LPSTR SourceFileName, // Used for redist case
99 BOOL CopyFromSourceOnly,
100 BOOL StripPrivate
103 BOOL
104 BinplaceCopyManifest (
105 LPSTR DestinationFile,
106 LPSTR SourceFileName, // Used for redist case
107 BOOL CopyFromSourceOnly,
108 BOOL StripPrivate
112 BOOL
113 SourceIsNewer(
114 IN LPSTR SourceFile,
115 IN LPSTR TargetFile
118 BOOL
119 SetupModeRetailFile(
120 IN LPSTR FullFileName,
121 IN LPSTR FileNamePart,
122 OUT PBOOL PutInDump
125 __inline BOOL
126 SearchOneDirectory(
127 IN LPSTR Directory,
128 IN LPSTR FileToFind,
129 IN LPSTR SourceFullName,
130 IN LPSTR SourceFilePart,
131 OUT PBOOL FoundInTree
135 // This was way too slow. Just say we didn't find the file.
137 *FoundInTree = FALSE;
138 return(TRUE);
141 BOOL
142 FileExists(
143 IN LPCSTR FileName,
144 OUT PWIN32_FIND_DATA FindData
149 CLASS_TABLE CommonClassTable[] = {
150 {"retail", "."},
151 {"windows", "."},
152 {NULL,NULL}
155 CLASS_TABLE i386SpecificClassTable[] = {
156 {"hal","system32"},
157 {"printer","system32\\spool\\drivers\\w32x86"},
158 {"prtprocs","system32\\spool\\prtprocs\\w32x86"},
159 {NULL,NULL}
163 CLASS_TABLE ia64SpecificClassTable[] = {
164 {"hal",".."},
165 {"printer","system32\\spool\\drivers\\w32ia64"},
166 {"prtprocs","system32\\spool\\prtprocs\\w32ia64"},
167 {NULL,NULL}
171 // Names of sections in layout.inx
173 LPCSTR szSourceDisksFiles = "SourceDisksFiles";
174 LPCSTR szSourceDisksX86 = "SourceDisksFiles.x86";
175 LPCSTR szSourceDisksIA64 = "SourceDisksFiles.ia64";
177 typedef struct _PLACE_FILE_RECORD {
178 LPSTR FileNameEntry;
179 LPSTR FileClass;
180 } PLACE_FILE_RECORD, *PPLACE_FILE_RECORD;
182 int MaxNumberOfRecords;
183 int NumberOfRecords;
184 PPLACE_FILE_RECORD PlaceFileRecords;
186 int __cdecl
187 pfcomp(
188 const void *e1,
189 const void *e2
192 PPLACE_FILE_RECORD p1;
193 PPLACE_FILE_RECORD p2;
195 p1 = (PPLACE_FILE_RECORD)e1;
196 p2 = (PPLACE_FILE_RECORD)e2;
198 return (strcmp(p1->FileNameEntry,p2->FileNameEntry));
201 CHAR PlaceFileDir[4096];
202 CHAR PlaceFileClass[4096];
203 CHAR PlaceFileEntry[4096];
205 BOOL
206 SortPlaceFileRecord()
208 int cfield;
209 PPLACE_FILE_RECORD NewRecords;
211 NumberOfRecords = 0;
212 MaxNumberOfRecords = 0;
215 // get space for 6k records. Grow if need to.
217 MaxNumberOfRecords = 7000;
218 PlaceFileRecords = (PPLACE_FILE_RECORD) malloc( sizeof(*PlaceFileRecords)*MaxNumberOfRecords );
219 if ( !PlaceFileRecords ) {
220 return FALSE;
223 if (fseek(PlaceFile,0,SEEK_SET)) {
224 free(PlaceFileRecords);
225 PlaceFileRecords = NULL;
226 return FALSE;
229 while (fgets(PlaceFileDir,sizeof(PlaceFileDir),PlaceFile)) {
231 PlaceFileEntry[0] = '\0';
232 PlaceFileClass[0] = '\0';
234 cfield = sscanf(
235 PlaceFileDir,
236 // "%s %[A-Za-z0-9.,_!@#\\$+=%^&()~ -]s",
237 "%s %s",
238 PlaceFileEntry,
239 PlaceFileClass
242 if (cfield <= 0 || PlaceFileEntry[0] == ';') {
243 continue;
246 PlaceFileRecords[NumberOfRecords].FileNameEntry = (LPSTR) malloc( strlen(PlaceFileEntry)+1 );
247 PlaceFileRecords[NumberOfRecords].FileClass = (LPSTR) malloc( strlen(PlaceFileClass)+1 );
248 if (!PlaceFileRecords[NumberOfRecords].FileClass || !PlaceFileRecords[NumberOfRecords].FileNameEntry) {
249 if (PlaceFileRecords[NumberOfRecords].FileClass)
250 free(PlaceFileRecords[NumberOfRecords].FileClass);
251 if (PlaceFileRecords[NumberOfRecords].FileNameEntry)
252 free(PlaceFileRecords[NumberOfRecords].FileNameEntry);
253 free(PlaceFileRecords);
254 PlaceFileRecords = NULL;
255 return FALSE;
257 strcpy(PlaceFileRecords[NumberOfRecords].FileNameEntry,PlaceFileEntry);
258 strcpy(PlaceFileRecords[NumberOfRecords].FileClass,PlaceFileClass);
259 NumberOfRecords++;
260 if ( NumberOfRecords >= MaxNumberOfRecords ) {
261 MaxNumberOfRecords += 200;
262 NewRecords = (PPLACE_FILE_RECORD) realloc(
263 PlaceFileRecords,
264 sizeof(*PlaceFileRecords)*MaxNumberOfRecords
266 if ( !NewRecords ) {
267 PlaceFileRecords = NULL;
268 return FALSE;
270 PlaceFileRecords = NewRecords;
273 qsort((void *)PlaceFileRecords,(size_t)NumberOfRecords,(size_t)sizeof(*PlaceFileRecords),pfcomp);
274 return TRUE;
277 PPLACE_FILE_RECORD
278 LookupPlaceFileRecord(
279 LPSTR FileName
282 LONG High;
283 LONG Low;
284 LONG Middle = 0;
285 LONG Result;
288 // Lookup the name using a binary search.
291 if ( !PlaceFileRecords ) {
292 return NULL;
295 Low = 0;
296 High = NumberOfRecords - 1;
297 while (High >= Low) {
300 // Compute the next probe index and compare the import name
301 // with the export name entry.
304 Middle = (Low + High) >> 1;
305 Result = _stricmp(FileName, PlaceFileRecords[Middle].FileNameEntry);
307 if (Result < 0) {
308 High = Middle - 1;
310 } else if (Result > 0) {
311 Low = Middle + 1;
313 } else {
314 break;
318 if (High < Low) {
319 return NULL;
320 } else {
321 return &PlaceFileRecords[Middle];
325 BOOL
326 MakeSureDirectoryPathExists(
327 LPCSTR DirPath
330 LPSTR p, DirCopy;
331 DWORD dw;
333 // Make a copy of the string for editing.
335 DirCopy = (LPSTR)malloc(strlen(DirPath) + 1);
337 if (!DirCopy) {
338 return FALSE;
341 strcpy(DirCopy, DirPath);
343 p = DirCopy;
345 // If the second character in the path is "\", then this is a UNC
346 // path, and we should skip forward until we reach the 2nd \ in the path.
348 if ((*p == '\\') && (*(p+1) == '\\')) {
349 p++; // Skip over the first \ in the name.
350 p++; // Skip over the second \ in the name.
352 // Skip until we hit the first "\" (\\Server\).
354 while (*p && *p != '\\') {
355 p = CharNext(p);
358 // Advance over it.
360 if (*p) {
361 p++;
364 // Skip until we hit the second "\" (\\Server\Share\).
366 while (*p && *p != '\\') {
367 p = CharNext(p);
370 // Advance over it also.
372 if (*p) {
373 p++;
376 } else
377 // Not a UNC. See if it's <drive>:
378 if (*(p+1) == ':' ) {
380 p++;
381 p++;
383 // If it exists, skip over the root specifier
385 if (*p && (*p == '\\')) {
386 p++;
390 while( *p ) {
391 if ( *p == '\\' ) {
392 *p = '\0';
393 dw = GetFileAttributesA(DirCopy);
394 // Nothing exists with this name. Try to make the directory name and error if unable to.
395 if ( dw == 0xffffffff ) {
396 if ( !CreateDirectory(DirCopy,NULL) ) {
397 if( GetLastError() != ERROR_ALREADY_EXISTS ) {
398 free(DirCopy);
399 return FALSE;
402 } else {
403 if ( (dw & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ) {
404 // Something exists with this name, but it's not a directory... Error
405 free(DirCopy);
406 return FALSE;
410 *p = '\\';
412 p = CharNext(p);
415 free(DirCopy);
416 return TRUE;
420 int __cdecl
421 main(
422 int argc,
423 char **argv
426 char c, *p, *OverrideFlags, *s, **newargv;
427 int i, n;
429 fUsage = FALSE;
430 fVerbose = FALSE;
431 fTestMode = FALSE;
432 fKeepAttributes = FALSE;
433 fDontExit = FALSE;
434 fSrcControl = FALSE;
435 fDbgControl = FALSE;
436 NormalPlaceSubdir = NULL;
438 if (argc < 2) {
439 goto showUsage;
443 if (!(PlaceFileName = getenv( "BINPLACE_PLACEFILE" ))) {
444 if ((PlaceFileName = getenv("_NTDRIVE")) == NULL) {
445 PlaceFileName = DEFAULT_NTDRIVE;
447 strcpy((PCHAR) PlaceFilePath, PlaceFileName);
448 if ((PlaceFileName = getenv("_NTROOT")) == NULL) {
449 PlaceFileName = DEFAULT_NTROOT;
451 strcat((PCHAR) PlaceFilePath, PlaceFileName);
452 strcat((PCHAR) PlaceFilePath, DEFAULT_PLACE_FILE);
453 PlaceFileName = (PCHAR) PlaceFilePath;
457 if (!(BinplaceLcDir = getenv( "BINPLACE_LCDIR" ))) {
458 BinplaceLcDir = DEFAULT_LCDIR;
463 CurrentImageName = NULL;
465 OverrideFlags = getenv( "BINPLACE_OVERRIDE_FLAGS" );
466 if (OverrideFlags != NULL) {
467 s = OverrideFlags;
468 n = 0;
469 while (*s) {
470 while (*s && *s <= ' ')
471 s += 1;
472 if (*s) {
473 n += 1;
474 while (*s > ' ')
475 s += 1;
477 if (*s)
478 *s++ = '\0';
482 if (n) {
483 newargv = malloc( (argc + n + 1) * sizeof( char * ) );
484 memcpy( &newargv[n], argv, argc * sizeof( char * ) );
485 argv = newargv;
486 argv[ 0 ] = argv[ n ];
487 argc += n;
488 s = OverrideFlags;
489 for (i=1; i<=n; i++) {
490 while (*s && *s <= ' ')
491 s += 1;
492 argv[ i ] = s;
493 while (*s++)
499 while (--argc) {
500 p = *++argv;
501 if (*p == '-') {
502 if (_stricmp(p + 1, "ChangeAsmsToRetailForSymbols") == 0) {
503 fChangeAsmsToRetailForSymbols = TRUE;
504 } else {
505 while ((c = *++p))
506 switch (toupper( c )) {
507 case '?':
508 fUsage = TRUE;
509 break;
512 case 'B':
513 argc--, argv++;
514 NormalPlaceSubdir = *argv;
515 break;
517 case 'C':
518 if (*(p+1) == 'I' || *(p+1) == 'i') {
519 char *q;
521 argc--, argv++;
522 p = *argv;
523 ImageCheck.RC = atoi(p);
524 if (!ImageCheck.RC) {
525 fprintf( stderr, "BINPLACE : error BNP0000: Invalid return code for -CI option\n");
526 fUsage = TRUE;
528 while (*p++ != ',');
529 q = p;
530 ImageCheck.Argc = 0;
531 while (*p != '\0')
532 if (*p++ == ',') ImageCheck.Argc++;
533 // last option plus extra args for Image file and Argv NULL
534 ImageCheck.Argc += 3;
535 ImageCheck.Argv = malloc( ImageCheck.Argc * sizeof( void * ) );
536 for ( i = 0; i <= ImageCheck.Argc - 3; i++) {
537 ImageCheck.Argv[i] = q;
538 while (*q != ',' && *q != '\0') q++;
539 *q++ = '\0';
541 p--;
542 ImageCheck.Argv[ImageCheck.Argc-1] = NULL;
543 } else {
545 break;
547 case 'D':
549 argc--, argv++;
550 DumpOverride = *argv;
552 break;
554 case 'E':
555 fDontExit = TRUE;
556 break;
558 case 'F':
559 break;
562 case 'K':
563 fKeepAttributes = TRUE;
564 break;
567 case 'M':
568 fMakeErrorOnDumpCopy = TRUE;
569 break;
571 case 'N':
572 argc--, argv++;
573 break;
575 case 'O':
576 argc--, argv++;
577 if (PlaceRootName != NULL) {
578 strcpy(szAltPlaceRoot,PlaceRootName);
579 strcat(szAltPlaceRoot,"\\");
580 strcat(szAltPlaceRoot,*argv);
581 PlaceRootName = szAltPlaceRoot;
583 break;
585 case 'P':
586 argc--, argv++;
587 PlaceFileName = *argv;
588 break;
590 case 'Q':
591 fDontLog = TRUE;
592 break;
594 case 'R':
595 argc--, argv++;
596 PlaceRootName = *argv;
597 break;
599 case 'S':
600 argc--, argv++;
601 SymbolFilePath = *argv;
602 break;
604 case 'T':
605 fTestMode = TRUE;
606 break;
609 case 'V':
610 fVerbose = TRUE;
611 break;
613 case 'W':
614 break;
616 case 'X':
617 break;
619 case 'Y':
620 break;
624 default:
625 fprintf( stderr, "BINPLACE : error BNP0000: Invalid switch - /%c\n", c );
626 fUsage = TRUE;
627 break;
631 if ( fUsage ) {
632 showUsage:
633 fputs(
634 "usage: binplace [switches] image-names... \n"
635 "where: [-?] display this message\n"
636 " [-b subdir] put file in subdirectory of normal place\n"
637 " [-d dump-override]\n"
638 " [-e] don't exit if a file in list could not be binplaced\n"
639 " [-k] keep attributes (don't turn off archive)\n"
640 " [-o place-root-subdir] alternate project subdirectory\n"
641 " [-p place-file]\n"
642 " [-q] suppress writing to log file %BINPLACE_LOG%\n"
643 " [-r place-root]\n"
644 " [-s Symbol file path] split symbols from image files\n"
645 " [-t] test mode\n"
646 " [-v] verbose output\n"
647 " [-ci <rc,app,-arg0,-argv1,-argn>]\n"
648 " rc=application error return code,\n"
649 " app=application used to check images,\n"
650 " -arg0..-argn=application options\n"
651 "\n"
652 "BINPLACE looks for the following environment variable names:\n"
653 " BINPLACE_OVERRIDE_FLAGS - may contain additional switches\n"
654 " BINPLACE_PLACEFILE - default value for -p flag\n"
655 "\n"
656 ,stderr
659 exit(BINPLACE_ERR);
661 } else {
662 WIN32_FIND_DATA FindData;
663 HANDLE h;
665 if (!PlaceRootName) {
666 // If there's no root, just exit.
667 exit(BINPLACE_OK);
671 h = FindFirstFile(p,&FindData);
672 if (h != INVALID_HANDLE_VALUE) {
673 FindClose(h);
674 if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
675 if ( fVerbose ) {
676 fprintf(stdout,"BINPLACE : warning BNP0000: ignoring directory %s\n",p);
678 continue;
682 CurrentImageName = p;
686 // If the master place file has not been opened, open
687 // it up.
690 if ( !PlaceFile ) {
691 PlaceFile = fopen(PlaceFileName, "rt");
692 if (!PlaceFile) {
693 fprintf(stderr,"BINPLACE : fatal error BNP0000: fopen of placefile %s failed %d\n",PlaceFileName,GetLastError());
694 exit(BINPLACE_ERR);
699 if (PlaceRootName == NULL) {
700 fprintf(stderr,"BINPLACE : fatal error BNP0000: Place Root not defined - exiting.\n");
701 exit(BINPLACE_ERR);
704 // If the SymbolFilePath has not been set, make a default value.
705 if (!SymbolFilePath) {
706 strcpy(DefaultSymbolFilePath, PlaceRootName);
707 strcat(DefaultSymbolFilePath, "\\symbols");
708 SymbolFilePath = DefaultSymbolFilePath;
711 if ( !PlaceTheFile() ) {
712 if (fDontExit) {
713 fprintf(stderr,"BINPLACE : error BNP0000: Unable to place file %s.\n",CurrentImageName);
714 } else {
715 fprintf(stderr,"BINPLACE : fatal error BNP0000: Unable to place file %s - exiting.\n",CurrentImageName);
716 exit(BINPLACE_ERR);
722 exit(BINPLACE_OK);
723 return BINPLACE_OK;
726 BOOL
727 PlaceTheFile()
729 CHAR FullFileName[MAX_PATH+1];
730 LPSTR PlaceFileNewName;
731 LPSTR FilePart;
732 LPSTR Separator;
733 LPSTR PlaceFileClassPart;
734 DWORD cb;
735 int cfield;
736 PCLASS_TABLE ClassTablePointer;
737 BOOLEAN ClassMatch;
738 BOOL fCopyResult = FALSE;
739 LPSTR Extension;
740 BOOL PutInDebug = FALSE;
741 BOOL PutInLcDir = FALSE;
743 cb = GetFullPathName(CurrentImageName,MAX_PATH+1,FullFileName,&FilePart);
745 if (!cb || cb > MAX_PATH+1) {
746 fprintf(stderr,"BINPLACE : fatal error BNP0000: GetFullPathName failed %d\n",GetLastError());
747 return FALSE;
751 if (fVerbose) {
752 fprintf(stdout,"BINPLACE : warning BNP0000: Looking at file %s\n",FilePart);
755 Extension = strrchr(FilePart,'.');
756 if (Extension) {
757 if (!_stricmp(Extension,".DBG")) {
758 PutInDebug = TRUE;
760 else if (!_stricmp(Extension,".LC")) {
761 PutInLcDir = TRUE;
765 if (!DumpOverride) {
767 if (fseek(PlaceFile,0,SEEK_SET)) {
768 fprintf(stderr,"BINPLACE : fatal error BNP0000: fseek(PlaceFile,0,SEEK_SET) failed %d\n",GetLastError());
769 return FALSE;
771 while (fgets(PlaceFileDir,sizeof(PlaceFileDir),PlaceFile)) {
773 PlaceFileEntry[0] = '\0';
774 PlaceFileClass[0] = '\0';
776 cfield = sscanf(
777 PlaceFileDir,
778 // "%s %[A-Za-z0-9.,_!@#\\$+=%^&()~ -]s",
779 "%s %s",
780 PlaceFileEntry,
781 PlaceFileClass
784 if (cfield <= 0 || PlaceFileEntry[0] == ';') {
785 continue;
788 if ((PlaceFileNewName = strchr(PlaceFileEntry,'!'))) {
789 *PlaceFileNewName++ = '\0';
792 if (!_stricmp(FilePart,PlaceFileEntry)) {
794 // now that we have the file and class, search the
795 // class tables for the directory.
797 Separator = PlaceFileClass - 1;
798 while (Separator) {
800 PlaceFileClassPart = Separator+1;
801 Separator = strchr(PlaceFileClassPart,':');
802 if (Separator) {
803 *Separator = '\0';
807 // If the class is "retail" and we're in Setup mode,
808 // handle this file specially. Setup mode is used to
809 // incrementally binplace files into an existing installation.
811 SetupFilePath[0] = '\0';
813 PlaceFileDir[0]='\0';
814 ClassMatch = FALSE;
815 ClassTablePointer = &CommonClassTable[0];
816 while (ClassTablePointer->ClassName) {
817 if (!_stricmp(ClassTablePointer->ClassName,PlaceFileClassPart)) {
818 strcpy(PlaceFileDir,ClassTablePointer->ClassLocation);
819 ClassMatch = TRUE;
821 break;
824 ClassTablePointer++;
827 if (!ClassMatch) {
829 // Search Specific classes
831 // We need to support cross compiling here.
832 LPTSTR platform;
834 ClassTablePointer = &i386SpecificClassTable[0];
835 if ((platform = getenv("IA64")) != NULL) {
836 ClassTablePointer = &ia64SpecificClassTable[0];
838 while (ClassTablePointer->ClassName) {
840 if (!_stricmp(ClassTablePointer->ClassName,PlaceFileClassPart)) {
841 strcpy(PlaceFileDir,ClassTablePointer->ClassLocation);
842 ClassMatch = TRUE;
843 break;
846 ClassTablePointer++;
850 if (!ClassMatch) {
852 char * asterisk;
855 // Still not found in class table. Use the class as the
856 // directory
859 if ( fVerbose ) {
860 fprintf(stderr,"BINPLACE : warning BNP0000: Class %s Not found in Class Tables\n",PlaceFileClassPart);
862 if ((asterisk = strchr(PlaceFileClassPart, '*'))) {
864 // Expand * to platform
866 LPTSTR platform;
867 ULONG PlatformSize;
868 LPTSTR PlatformPath;
870 PlatformSize = 4;
871 PlatformPath = TEXT("i386");
872 if ((platform = getenv("IA64")) != NULL) {
873 PlatformPath = TEXT("ia64");
874 } else if ((platform = getenv("AMD64")) != NULL) {
875 PlatformSize = 5;
876 PlatformPath = TEXT("amd64");
879 strncpy(PlaceFileDir,PlaceFileClassPart, (int)(asterisk - PlaceFileClassPart));
880 strcpy(PlaceFileDir + (asterisk - PlaceFileClassPart), PlatformPath);
881 strcpy(PlaceFileDir + (asterisk - PlaceFileClassPart) + PlatformSize, asterisk + 1);
883 } else {
884 strcpy(PlaceFileDir,PlaceFileClassPart);
888 if (SetupFilePath[0] == '\0') {
889 strcpy(SetupFilePath, PlaceFileDir);
890 strcat(SetupFilePath, "\\");
891 strcat(SetupFilePath, FilePart);
894 if (NormalPlaceSubdir) {
895 strcat(PlaceFileDir,"\\");
896 strcat(PlaceFileDir,NormalPlaceSubdir);
899 fCopyResult = CopyTheFile(FullFileName,FilePart,PlaceFileDir,PlaceFileNewName);
900 if (!fCopyResult) {
901 break;
905 return(fCopyResult);
910 if (fMakeErrorOnDumpCopy) {
911 fprintf(stderr, "BINPLACE : error BNP0000: File '%s' is not listed in '%s'. Copying to dump.\n", FullFileName, PlaceFileName);
914 return CopyTheFile(
915 FullFileName,
916 FilePart,
917 PutInDebug ? "Symbols" : (PutInLcDir ? BinplaceLcDir : (DumpOverride ? DumpOverride : DEFAULT_DUMP)),
918 NULL
923 BOOL
924 CopyTheFile(
925 LPSTR SourceFileName,
926 LPSTR SourceFilePart,
927 LPSTR DestinationSubdir,
928 LPSTR DestinationFilePart
931 CHAR DestinationFile[MAX_PATH+1];
932 CHAR TmpDestinationDir[MAX_PATH];
933 CHAR *TmpSymbolFilePath;
935 if ( !PlaceRootName ) {
936 fprintf(stderr,"BINPLACE : warning BNP0000: PlaceRoot is not specified\n");
937 return FALSE;
941 strcpy(DestinationFile,PlaceRootName);
942 strcat(DestinationFile,"\\");
943 strcat(DestinationFile,DestinationSubdir);
944 strcat(DestinationFile,"\\");
946 strcpy (TmpDestinationDir, DestinationFile);
949 if (!MakeSureDirectoryPathExists(DestinationFile)) {
950 fprintf(stderr, "BINPLACE : error BNP0000: Unable to create directory path '%s' (%u)\n",
951 DestinationFile, GetLastError()
955 if (DestinationFilePart) {
956 strcat(DestinationFile,DestinationFilePart);
957 } else {
958 strcat(DestinationFile,SourceFilePart);
961 if (
962 (fVerbose || fTestMode)) {
963 fprintf(stdout,"BINPLACE : warning BNP0000: place %s in %s\n",SourceFileName,DestinationFile);
967 if (SourceIsNewer(SourceFileName,DestinationFile)) {
968 fprintf(stdout, "binplace %s\n", SourceFileName);
972 if (!fTestMode) {
974 // In Setup mode, copy the file only if it's newer than
975 // the one that's already there.
977 if (SourceIsNewer(SourceFileName,DestinationFile)) {
978 if (fVerbose) {
979 fprintf(stdout,"BINPLACE : warning BNP0000: copy %s to %s\n",SourceFileName,DestinationFile);
981 } else {
982 return(TRUE);
985 SetFileAttributes(DestinationFile,FILE_ATTRIBUTE_NORMAL);
988 if ( !CopyFile(SourceFileName,DestinationFile, FALSE)) {
989 fprintf(stderr,"BINPLACE : warning BNP0000: CopyFile(%s,%s) failed %d\n",SourceFileName,DestinationFile,GetLastError());
991 return FALSE;
994 if (!fKeepAttributes)
995 SetFileAttributes(DestinationFile,FILE_ATTRIBUTE_NORMAL);
998 TmpSymbolFilePath = SymbolFilePath;
1001 BinplaceCopyPdb(TmpSymbolFilePath, SourceFileName, TRUE, FALSE);
1002 // Copy the ILDB to be next to the exe
1003 BinplaceCopyIldb(TmpDestinationDir, SourceFileName, TRUE, FALSE);
1004 // Copy the manifest to be next to the exe
1005 BinplaceCopyManifest(TmpDestinationDir, SourceFileName, TRUE, FALSE);
1007 } else {
1010 return TRUE;
1015 BOOL
1016 SourceIsNewer(
1017 IN LPSTR SourceFile,
1018 IN LPSTR TargetFile
1021 return TRUE;
1027 BOOL
1028 BinplaceCopyPdb (
1029 LPSTR DestinationFile,
1030 LPSTR SourceFileName,
1031 BOOL CopyFromSourceOnly,
1032 BOOL StripPrivate
1035 CHAR Drive[_MAX_DRIVE];
1036 CHAR Dir[_MAX_DIR];
1037 CHAR Filename[_MAX_FNAME];
1038 CHAR Ext[_MAX_EXT];
1039 CHAR SourcePdbName[_MAX_PATH];
1040 CHAR DestinationPdbName[_MAX_PATH];
1042 _splitpath(SourceFileName, Drive, Dir, Filename, Ext);
1043 _makepath(SourcePdbName, Drive, Dir, Filename, ".pdb");
1044 if (GetFileAttributesA(SourcePdbName) != 0xffffffff) {
1046 // Source file exists
1048 strcpy(DestinationPdbName, DestinationFile);
1049 strcat(DestinationPdbName, "\\");
1050 strcat(DestinationPdbName, &Ext[1]);
1051 strcat(DestinationPdbName, "\\");
1052 strcat(DestinationPdbName, Filename);
1053 strcat(DestinationPdbName, ".pdb");
1055 if (fVerbose || fTestMode) {
1056 fprintf(stdout,"BINPLACE : warning BNP0000: place %s in %s\n", SourcePdbName, DestinationPdbName);
1059 if (!MakeSureDirectoryPathExists(DestinationPdbName)) {
1060 return FALSE;
1062 if (!CopyFileA(SourcePdbName, DestinationPdbName, FALSE)) {
1063 return FALSE;
1065 SetFileAttributes(DestinationPdbName,FILE_ATTRIBUTE_NORMAL);
1066 return TRUE;
1068 return FALSE;
1071 BOOL
1072 BinplaceCopyIldb (
1073 LPSTR DestinationFile,
1074 LPSTR SourceFileName,
1075 BOOL CopyFromSourceOnly,
1076 BOOL StripPrivate
1079 CHAR Drive[_MAX_DRIVE];
1080 CHAR Dir[_MAX_DIR];
1081 CHAR Filename[_MAX_FNAME];
1082 CHAR Ext[_MAX_EXT];
1083 CHAR SourceIldbName[_MAX_PATH];
1084 CHAR DestinationIldbName[_MAX_PATH];
1086 _splitpath(SourceFileName, Drive, Dir, Filename, Ext);
1087 _makepath(SourceIldbName, Drive, Dir, Filename, ".ildb");
1088 if (GetFileAttributesA(SourceIldbName) != 0xffffffff) {
1090 // Source file exists
1092 strcpy(DestinationIldbName, DestinationFile);
1093 strcat(DestinationIldbName, "\\");
1094 strcat(DestinationIldbName, Filename);
1095 strcat(DestinationIldbName, ".ildb");
1097 if (fVerbose || fTestMode) {
1098 fprintf(stdout,"BINPLACE : warning BNP0000: place %s in %s\n", SourceIldbName, DestinationIldbName);
1101 if (!MakeSureDirectoryPathExists(DestinationIldbName)) {
1102 return FALSE;
1104 if (!CopyFileA(SourceIldbName, DestinationIldbName, FALSE)) {
1105 return FALSE;
1107 SetFileAttributes(DestinationIldbName,FILE_ATTRIBUTE_NORMAL);
1108 return TRUE;
1110 return FALSE;
1113 BOOL
1114 BinplaceCopyManifest (
1115 LPSTR DestinationFile,
1116 LPSTR SourceFileName,
1117 BOOL CopyFromSourceOnly,
1118 BOOL StripPrivate
1121 CHAR Drive[_MAX_DRIVE];
1122 CHAR Dir[_MAX_DIR];
1123 CHAR Filename[_MAX_FNAME];
1124 CHAR Ext[_MAX_EXT];
1125 CHAR SourceManifestName[_MAX_PATH];
1126 CHAR DestinationManifestName[_MAX_PATH];
1128 _splitpath(SourceFileName, Drive, Dir, Filename, Ext);
1129 _makepath(SourceManifestName, Drive, Dir, Filename, Ext);
1130 strcat(SourceManifestName, ".manifest");
1132 if (GetFileAttributesA(SourceManifestName) != 0xffffffff) {
1134 // Source file exists
1136 strcpy(DestinationManifestName, DestinationFile);
1137 strcat(DestinationManifestName, "\\");
1138 strcat(DestinationManifestName, Filename);
1139 strcat(DestinationManifestName, Ext);
1140 strcat(DestinationManifestName, ".manifest");
1142 if (fVerbose || fTestMode) {
1143 fprintf(stdout,"BINPLACE : warning BNP0000: place %s in %s\n", SourceManifestName, DestinationManifestName);
1146 if (!MakeSureDirectoryPathExists(DestinationManifestName)) {
1147 return FALSE;
1149 if (!CopyFileA(SourceManifestName, DestinationManifestName, FALSE)) {
1150 return FALSE;
1152 SetFileAttributes(DestinationManifestName,FILE_ATTRIBUTE_NORMAL);
1153 return TRUE;
1155 return FALSE;
1158 BOOL
1159 FileExists(
1160 IN LPCSTR FileName,
1161 OUT PWIN32_FIND_DATA FindData
1164 BOOL Found;
1165 HANDLE FindHandle;
1168 FindHandle = FindFirstFile(FileName,FindData);
1169 if (FindHandle == INVALID_HANDLE_VALUE) {
1170 Found = FALSE;
1171 } else {
1172 FindClose(FindHandle);
1173 Found = TRUE;
1176 return(Found);